package com.myspringboot.dao.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Created by guohuixin on 2017/12/2.
 */
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.myspringboot.dao.mapper")
public class DaoConfig {

    /**
     * 主数据源
     * @return
     */
    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    @Primary
    public DataSource masterDataSource(){
        return DataSourceBuilder.create().build();
    }

    /**
     * c从数据源
     * @return
     */
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "slave")
    public DataSource slaveDataSource(){
        return DataSourceBuilder.create().build();
    }


    @Bean(name="sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        //设置数据源
        bean.setDataSource(dataSource);
        //该属性可以给包中的类注册别名，注册后可以直接使用类名，而不用使用全限定的类名（就是不用包含包名）。
        //参数包名下面为数据体实体类
        bean.setTypeAliasesPackage("com.myspringboot.dao.domain");

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        /**
         * 设置mapper文件路径,mapper下面的xml分别针对上面的setTypeAliasesPackage设置的数据库表实体类的sql语句；
         * 一般setTypeAliasesPackage中有几个实体类，在Mapper中就会对应几个xml文件，命名一般两者之间都是对应的
         * mapper/*.xml存在于resources文件中
         * 引入mapper接口包的形式，可以通过这种形式这只，同样可以在mybatis-config.xml此配置文件中进行设置<mappers><package name="com.yu.mapper"/></mappers>
         */
        bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));

        //设置mybatis-config文件的路径，mybatis-config.xml为核心配置，参考：http://ju.outofmemory.cn/entry/94633
        bean.setConfigLocation(resolver.getResource("classpath:mybatis-config.xml"));
        return bean.getObject();
    }


    /**
     * 会话
     * @param sqlSessionFactory
     * @return
     */
    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 事务管理
     * @param dataSource
     * @return
     */
    @Bean(name = "dataSourceTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("masterDataSource")DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "mapperScanner")
    public MapperScannerConfigurer mapperScannerConfigurer (){
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        /**
         * 如果只有一个DataSource的时候 就不需要设置前面两个了，如果有多个DataSource就需要设置
         * setBackPackage设置对应实体类的mapperw文件，里面存放了针对每一个实体类中的sql语句的定义，然后在对应的mapper.xml编写具体的sql语句
         * 此种定义的方法名称 例如：int select**ByID(int id), 方法名称为select**ByID ，此时在实体类对应的mapper.xml 中一定有一个对应的select语句
         * 其中id名称就是这个方法名称 即<select id="select**ByID">具体的select语句</select>
         *
         * setBasePackage可以单个配置，也可以通过下面的方式直接对mapper包进行设置，会自动扫描此包下面的所有的文件
         */
        configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        configurer.setSqlSessionTemplateBeanName("sqlSessionTemplate");
        configurer.setBasePackage("com.myspringboot.dao.mapper");

        // 配置通用的mapper
        Properties properties = new Properties();
        properties.setProperty("mappers", "com.myspringboot.dao.bm.BaseMapper");
        properties.setProperty("notEmpty", "false");
        properties.setProperty("IDENTITY", "MYSQL");
        configurer.setProperties(properties);
        return configurer;
    }
}
